home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 42
/
Amiga Format AFCD42 (Issue 126, Aug 1999).iso
/
-serious-
/
programming
/
other
/
jikes
/
src
/
long.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-14
|
15KB
|
627 lines
// $Id: long.cpp,v 1.4 1999/02/10 14:53:01 shields Exp $
//
// This software is subject to the terms of the IBM Jikes Compiler
// License Agreement available at the following URL:
// http://www.ibm.com/research/jikes.
// Copyright (C) 1996, 1998, International Business Machines Corporation
// and others. All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
#include "config.h"
#include <iostream.h>
#include "long.h"
#include "double.h"
//
// Note that the minimum long value, (0x80000000, 0x00000000), can be represented
// exactly in a double field. However, the maximum long value, (0x7FFFFFFF, 0xFFFFFFFF)
// cannot. To test if the double quantity "a" fits in a long range we will test whether
// or not:
// (a >= min_long) && (-a > min_long)
//
BaseLong::operator LongInt()
{
return LongInt(HighWord(), LowWord());
}
BaseLong::operator ULongInt()
{
return ULongInt(HighWord(), LowWord());
}
bool BaseLong::operator== (BaseLong op)
{
return ((HighWord() == op.HighWord()) && (LowWord() == op.LowWord()));
}
bool BaseLong::operator!= (BaseLong op)
{
return ((HighWord() != op.HighWord()) || (LowWord() != op.LowWord()));
}
bool BaseLong::operator!()
{
return (*this == 0);
}
BaseLong BaseLong::operator~()
{
return BaseLong(~HighWord(), ~LowWord());
}
BaseLong BaseLong::operator^ (BaseLong op)
{
return BaseLong(HighWord() ^ op.HighWord(), LowWord() ^ op.LowWord());
}
BaseLong& BaseLong::operator^= (BaseLong op)
{
*this = *this ^ op;
return *this;
}
BaseLong BaseLong::operator| (BaseLong op)
{
return BaseLong(HighWord() | op.HighWord(), LowWord() | op.LowWord());
}
BaseLong& BaseLong::operator|= (BaseLong op)
{
*this = *this | op;
return *this;
}
BaseLong BaseLong::operator& (BaseLong op)
{
return BaseLong(HighWord() & op.HighWord(), LowWord() & op.LowWord());
}
BaseLong& BaseLong::operator&= (BaseLong op)
{
*this = *this & op;
return *this;
}
bool BaseLong::operator&& (BaseLong op)
{
return (*this != 0) && (op != 0);
}
bool BaseLong::operator|| (BaseLong op)
{
return (*this != 0) || (op != 0);
}
BaseLong BaseLong::operator<< (BaseLong op)
{
u4 n = op.LowWord(); // Always treat this value as positive, since negative values are not allowed
//
// Note that this function assumes that for two 32-bit integers
// x << y, where y = 0, is well-defined and that the result is
// the value x. This is true in Ansi-C and C++ but not true in
// old versions of C (See Kernighan and Ritchie).
// Note also that in shifting a 32-bit word, if y >= 32 then the
// result is unpredictable. On Aix, xlC will produce the result 0(good!)
// whereas on windows the Microsoft compiler produces the value of x(very bad !).
// That is the reason why we have the initial special check for (n == 0).
//
if(n == 0)
return *this;
else if(n < 32)
return BaseLong((HighWord() << n) |
(LowWord() >> (32 - n)), LowWord() << n);
else
return BaseLong(LowWord() << (n - 32), 0);
}
BaseLong& BaseLong::operator<<= (BaseLong op)
{
*this = *this << op;
return *this;
}
BaseLong BaseLong::operator+ (BaseLong op)
{
u4 ushort1 = (LowWord() & 0xFFFF) + (op.LowWord() & 0xFFFF),
ushort2 = (ushort1 >> 16) + (LowWord() >> 16) + (op.LowWord() >> 16),
ushort3 = (ushort2 >> 16) + (HighWord() & 0xFFFF) + (op.HighWord() & 0xFFFF),
ushort4 = (ushort3 >> 16) + (HighWord() >> 16) + (op.HighWord() >> 16);
return BaseLong((ushort3 & 0xFFFF) | (ushort4 << 16), (ushort1 & 0xFFFF) | (ushort2 << 16));
}
BaseLong& BaseLong::operator+= (BaseLong op)
{
*this = *this + op;
return *this;
}
BaseLong BaseLong::operator++ (int dummy)
{
BaseLong temp = *this;
*this += 1;
return temp;
}
BaseLong BaseLong::operator++ ()
{
*this += 1;
return *this;
}
BaseLong BaseLong::operator- ()
{
return ~(*this) + 1;
}
BaseLong BaseLong::operator- (BaseLong op)
{
return *this + (-op);
}
BaseLong& BaseLong::operator-= (BaseLong op)
{
*this = *this - op;
return *this;
}
BaseLong BaseLong::operator-- (int dummy)
{
BaseLong temp = *this;
*this -= 1;
return temp;
}
BaseLong BaseLong::operator-- ()
{
*this -= 1;
return *this;
}
BaseLong BaseLong::operator* (BaseLong op)
{
u4 x0 = this -> LowWord() & 0xFFFF,
x1 = this -> LowWord() >> 16,
x2 = this -> HighWord() & 0xFFFF,
x3 = this -> HighWord() >> 16;
u4 y0 = op.LowWord() & 0xFFFF,
y1 = op.LowWord() >> 16,
y2 = op.HighWord() & 0xFFFF,
y3 = op.HighWord() >> 16;
BaseLong result = BaseLong(0, x0 * y0);
BaseLong part1 = BaseLong(0, x0 * y1);
part1 <<= (1 << 4);
result += part1;
BaseLong part2 = BaseLong(0, x0 * y2);
part2 <<= (2 << 4);
result += part2;
BaseLong part3 = BaseLong(0, x0 * y3);
part3 <<= (3 << 4);
result += part3;
BaseLong part4 = BaseLong(0, x1 * y0);
part4 <<= (1 << 4);
result += part4;
BaseLong part5 = BaseLong(0, x1 * y1);
part5 <<= (2 << 4);
result += part5;
BaseLong part6 = BaseLong(0, x1 * y2);
part6 <<= (3 << 4);
result += part6;
BaseLong part7 = BaseLong(0, x1 * y3);
part7 <<= (4 << 4);
result += part7;
BaseLong part8 = BaseLong(0, x2 * y0);
part8 <<= (2 << 4);
result += part8;
BaseLong part9 = BaseLong(0, x2 * y1);
part9 <<= (3 << 4);
result += part9;
BaseLong part10 = BaseLong(0, x2 * y2);
part10 <<= (4 << 4);
result += part10;
BaseLong part11 = BaseLong(0, x2 * y3);
part11 <<= (5 << 4);
result += part11;
BaseLong part12 = BaseLong(0, x3 * y0);
part12 <<= (3 << 4);
result += part12;
BaseLong part13 = BaseLong(0, x3 * y1);
part13 <<= (4 << 4);
result += part13;
BaseLong part14 = BaseLong(0, x3 * y2);
part14 <<= (5 << 4);
result += part14;
BaseLong part15 = BaseLong(0, x3 * y3);
part15 <<= (6 << 4);
result += part15;
return result;
}
BaseLong& BaseLong::operator*= (BaseLong op)
{
*this = *this * op;
return *this;
}
BaseLong::BaseLong(u4 a, u4 b)
{
HighWord() = a;
LowWord() = b;
}
BaseLong::BaseLong(u4 a)
{
HighWord() = 0;
LowWord() = a;
}
BaseLong::BaseLong(i4 a)
{
LowWord() = a;
//
// Since the carry is not guaranteed to ripple, we cannot use this code.
//
// HighWord() = a >> 31;
//
HighWord() = (a < 0 ? 0xFFFFFFFF : 0x00000000);
}
void BaseLong::Divide(BaseLong dividend, BaseLong divisor, BaseLong "ient, BaseLong &remainder)
{
u4 high = dividend.HighWord(),
low = dividend.LowWord(),
remainder_high = 0;
for (int i = 0; i < 32; i++)
{
remainder_high = (remainder_high << 1) | (high >> 31);
high <<= 1;
if ((ULongInt) divisor <= remainder_high)
{
high++;
remainder_high -= divisor.LowWord();
}
}
remainder = BaseLong(0, remainder_high);
for (int j = 0; j < 32; j++)
{
remainder <<= 1;
remainder.LowWord() |= (low >> 31);
low <<= 1;
if ((ULongInt) divisor <= remainder)
{
low++;
remainder -= divisor;
}
}
quotient = BaseLong(high, low);
return;
}
void ULongInt::String(char *result)
{
ULongInt val = *this;
char *ptr = result;
do
{
*ptr++ = '0' + (val % 10).LowWord();
val /= 10;
} while (val != 0);
*ptr = U_NULL;
for (char *tail = ptr - 1; tail > result; tail--, result++)
{
char c = *tail;
*tail = *result;
*result = c;
}
return;
}
void LongInt::String(char *result)
{
ULongInt val;
if (HighWord() & 0x80000000)
{
*result++ = '-';
val = -(*this);
}
else val = *this;
val.String(result);
return;
}
ULongInt& ULongInt::operator/= (ULongInt op)
{
*this = *this / op;
return *this;
}
ULongInt ULongInt::operator/ (ULongInt op)
{
BaseLong quotient,
remainder;
Divide(*this, op, quotient, remainder);
return quotient;
}
ULongInt ULongInt::operator% (ULongIn